`ifndef CLK_SVH
`define CLK_SVH

class clock_generator extends uvm_component //  Class: clk_gen
    `uvm_component_utils(clock_generator)

    clock_if m_vif;
    real m_freq;
    freq_uni_type m_freq_unit;
    bit m_enable;
    bit m_init_value;

    bit m_ss_en;
    bit m_ss_freq;
    freq_uni_type m_ss_freq_unit;
    bit m_ss_range;

    real m_period;
    real m_half_period;
    protected event m_on_e;

    bit m_use_period;
    
    function new(string name = "clock_generator", uvm_component parent=null);
        super.new(name, parent);
    endfunction: new

    function void build_phase(uvm_phase phase);
       super.build_phase(phase);

       if(!uvm_config_db#(clock_if)::get(this, "", "vif", m_vif)) begin
          `uvm_fatal("CLOCK/NOVIF", "No Virtual interface specified or this BFM instance")
       end

       if(!uvm_config_db#(real)::get(this, "", "m_freq", m_freq)) begin
          `uvm_info("CLOCK/FREQ", "No Clock Frequency specified or this BFM instance, using default 100", UVM_MEDIUM)
           m_freq = 100.0;
       end

       if(!uvm_config_db#(freq_uni_type)::get(this, "", "m_freq_unit", m_freq_unit)) begin
          `uvm_info("CLOCK/FRQ/UNIT", "No Frequency Unit specified or this BFM instance, using default 100", UVM_MEDIUM)
           m_freq_unit = FRQ_MH;
       end
       if(!uvm_config_db#(bit)::get(this, "", "m_enable", m_enable)) begin
           m_enable = 1'b1;
       end

       if(!uvm_config_db#(bit)::get(this, "", "m_init_value", m_init_value)) begin
           m_init_value = 1'b0;
       end

       if(!uvm_config_db#(bit)::get(this, "", "m_use_period", m_use_period)) begin
           m_use_period = 1'b0;
       end

    endfunction : build_phase

    task run_phase(uvm_phase phase);
        `uvm_info("UVE_CLOCK", "start run phase", UVM_HIGH);
        m_vif.clk = m_init_value;
        if(m_use_period == 1'b0) begin
           m_period = get_period();
        end
        else begin
          if(!uvm_config_db#(real)::get(this, "", "m_period", m_period)) begin
            `uvm_info("CLOCK/FRQ", "No Clock period specified for this BFM instance, using default 100ns", UVM_MEDIUM);
            m_use_period = 100.0;
          end
        end
        m_half_period = m_period/2.0;
        while(1) begin
           if(m_enable)
              do_tick();
           else
              wait(m_one_e.triggered);
        end
        `uvm_info("UVE_CLOCK", "end run_phase", UVM_HIGH)
    endtask: run_phase

    task do_tick();
       #(m_half_period*1.0ns) m_vif.clk = ~m_vif.clk;
    endtask //automatic

    function real get_period();
        real period;
        case (m_freq_unit)
            FRQ_HZ: begin
                period = 1000000000.0/m_freq;
            end
            FRQ_KH: begin
                period = 1000000.0/m_freq;
            end
            FRQ_MH: begin
                period = 1000.0/m_freq;
            end
            FRQ_GH: begin
                period = 1.0/m_freq;
            end
            default: begin
                `uvm_fatal("CLOCK/FRQ/UNIT", "Fatal : illegal freqency unit detected")
            end
        endcase
        return period;
    endfunction

    function void stop_clk(); m_enable = 1'b0; endfunction
    
    function void resume_clk();
        m_enable = 1'b1;
        ->m_on_e;
    endfunction
endclass : clock_generator

`endif



    

    
endclass: clk_gen
 
